
#include "GamePlayer.h"
#include "GameDanger.h"
#include "ItemManager.h"
#include "CreatureManager.h"

GamePlayer::GamePlayer():
GameCreature() , 
mSocket( F_NULL ) , 
mValid( F_FALSE ) ,
mSQLCount( 0 ) ,
mAttackPet( F_NULL ) ,
mStone( 0 )
{
	memset( Account , 0 , MAX_NAME );
}



GamePlayer::~GamePlayer()
{

}


fvoid					GamePlayer::SendMsgToTeam()
{
	if ( mTeam )
	{
		fint32 count = mTeam->GetMemberCount();

		for ( fint32 i = 1 ; i < count ; i++ )
		{
			mTeam->GetMember( i )->SendMsg();
		}
	}
}

fvoid					GamePlayer::SendMsg()
{
	mSocket->SendMsg();
}


fvoid					GamePlayer::PackMsg( netMsgHead* msg )
{
	mSocket->ParkMsg( msg );
}

fvoid					GamePlayer::SetSocket( netSocket* socket )
{
	mSocket = socket;
}

netSocket*              GamePlayer::GetSocket()
{
	return mSocket;
}

fvoid					GamePlayer::Init()
{
	GameCreature::Init();

	mValid = F_TRUE;
}

fvoid					GamePlayer::Release()
{
	memset( Account , 0 , MAX_NAME );

	GameCreature::Release();

	mPet.clear();
	mPetAtHome.clear();

	mAttackPet = F_NULL;

	mValid = F_FALSE;
	mSQLCount = 0;

	mSocket = F_NULL;
}

fvoid					GamePlayer::EndFight()
{
	GameCreature::EndFight();

	GamePetMapIter iterEnd = mPet.end();

	for ( GamePetMapIter iter = mPet.begin() ; iter != iterEnd ; ++iter )
	{
		iter->second.EndFight();
	}
}

fvoid					GamePlayer::LevelUpPoint( fint32 type )
{
	if ( mData.LevelUpPoint )
	{
		mData.LevelUpPoint--;

		switch ( type )
		{
		case SACAT_VITALITY:
			{
				mData.Vitality++;

				mData.Base.MAXHP += GETMAXHP( 1 , 0 , 0 , 0 );
				mFightData.Base.MAXHP += GETMAXHP( 1 , 0 , 0 , 0 );
			}
			break;
		case SACAT_STRENGTH:
			{
				mData.Strength++;
				mData.Base.Attack++;
				mFightData.Base.Attack++;

				mData.Base.MAXHP += GETMAXHP( 0 , 1 , 0 , 0 );
				mFightData.Base.MAXHP += GETMAXHP( 0 , 1 , 0 , 0 );
			}
			break;
		case SACAT_TOUGHNESS:
			{
				mData.Toughness++;
				mData.Base.Defence++;
				mFightData.Base.Defence++;

				mData.Base.MAXHP += GETMAXHP( 0 , 0 , 1 , 0 );
				mFightData.Base.MAXHP += GETMAXHP( 0 , 0 , 1 , 0 );
			}
			break;
		case SACAT_DEXTERITY:
			{
				mData.Dexterity++;
				mData.Base.Quick++;
				mFightData.Base.Quick++;

				mData.Base.MAXHP += GETMAXHP( 0 , 0 , 0 , 1 );
				mFightData.Base.MAXHP += GETMAXHP( 0 , 0 , 0 , 1 );
			}
			break;
		}

	}
	else
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
	}

}

GamePet*				GamePlayer::GetPet( fint32 id )
{
	GamePetMapIter iter = mPet.find( id );

	if ( iter != mPet.end() )
	{
		return &( iter->second );
	}

	AddDanger( GAME_DESTRUCTIVELY_DANGER );

	return F_NULL;
}


fvoid					GamePlayer::SetPetName( fint32 id , const fbyte* name )
{
	GamePetMapIter iter = mPet.find( id );

	if ( iter == mPet.end() )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return;
	}

	iter->second.SetName( name );
}


fvoid					GamePlayer::SetPetType( fint32 id , fint32 type )
{
	if ( type < 0 || type >= GPT_COUNT )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return;
	}

	GamePetMapIter iter = mPet.find( id );

	if ( iter == mPet.end() )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return;
	}
	
	if ( type == GPT_ATTACK )
	{
		if ( mAttackPet )
		{
			AddDanger( GAME_DESTRUCTIVELY_DANGER );
			return;
		}

		iter->second.SetPetType( (GamePetType)type );
		SetAttackPet( &(iter->second) );
	}
	else
	{
		if ( iter->second.GetPetType() == GPT_ATTACK )
		{
			SetAttackPet( F_NULL );
		}

		iter->second.SetPetType( (GamePetType)type );
	}
	

}



//////////////////////////////////////////////////////////////////////////

fvoid					GamePlayer::UpdateFightData()
{
	GameCreature::UpdateFightData();

	for ( fint32 i = 0 ; i < SAET_COUNT ; i++ )
	{
		Item& item = mItemBag.GetEquip( i );
		ItemData* data = item.GetData();

		if ( data )
		{
			fint16 str = (data->Str1 + data->Str2) * 0.5f;
			fint16 tgh = (data->Tgh1 + data->Tgh2) * 0.5f;
			fint16 dex = (data->Dex1 + data->Dex2) * 0.5f;
			fint16 hp = (data->Hp1 + data->Hp2) * 0.5f;

			mFightData.Base.Attack += str;
			mFightData.Base.Defence += tgh;
			mFightData.Base.Quick += dex;

			mFightData.Base.MAXHP += hp;

			mFightData.Base.Charm += (data->Charm1 + data->Charm2) * 0.5f;
		}
	}

	if ( mFightData.Base.HP > mFightData.Base.MAXHP )
	{
		mFightData.Base.HP = mFightData.Base.MAXHP;
	}
	if ( mFightData.Base.MP > mFightData.Base.MAXMP )
	{
		mFightData.Base.MP = mFightData.Base.MAXMP;
	}

}


ItemBag&				GamePlayer::GetItemBag()
{
	return mItemBag;
}


fbool					GamePlayer::UseItem( fint32 i , fint32 p , fint32 t )
{
	if ( i < 0 || i >= MAX_ITEM )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return F_FALSE;
	}

	Item& item = mItemBag.GetItem( i );
	ItemData* data = item.GetData();

	if ( !data )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return F_FALSE;
	}

	switch ( data->Type )
	{
	case SAIT_FIST:
	case SAIT_AXE:
	case SAIT_CLUB:
	case SAIT_SPEAR:
	case SAIT_BOW:
		{
			mItemBag.EquipItem( i , SAET_RIGHT );
			UpdateFightData();
		}
		break;
	case SAIT_HELM:
		{
			mItemBag.EquipItem( i , SAET_HEAD );
			UpdateFightData();
		}
		break;
	case SAIT_ARMOUR:
		{
			mItemBag.EquipItem( i , SAET_BODY );
			UpdateFightData();
		}
		break;
	case SAIT_BRACELET:
	case SAIT_MUSIC:
	case SAIT_NECKLACE:
	case SAIT_RING:
	case SAIT_EARRING:
	case SAIT_AMULET:
		{
			if ( p == SAET_RING1 || p == SAET_RING2 )
			{
				mItemBag.EquipItem( i , p );
				UpdateFightData();
			}
		}
		break;
	case SAIT_OTHER:
	case SAIT_DISH:
		{
//			CommandFun1 fun = gItemManager->GetFun( data->UseItem.c_str() );
//
//			if ( fun )
//			{
//				fun( data , this , p , t );
//			}
//
//			item.Use();
		}
		break;
	}

	return F_TRUE;
}


fvoid					GamePlayer::EquipItem( fint32 i )
{
	
}


fvoid					GamePlayer::SwitchItem( fint32 i1 , fint32 i2 )
{
	if ( i1 < 0 || i1 >= MAX_ITEM || i2 < 0 || i2 >= MAX_ITEM || i1 == i2 )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return;
	}

	mItemBag.SwitchItem( i1 , i2 );
}


fvoid					GamePlayer::SwitchEquip( fint32 i1 , fint32 i2 )
{
	if ( i1 < 0 || i1 >= MAX_ITEM || i2 < 0 || i2 >= MAX_ITEM || i1 == i2 )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return;
	}

	if ( (i1 == SAET_RING1 && i2 == SAET_RING2) || (i1 == SAET_RING2 && i2 == SAET_RING1) )
	{
		mItemBag.SwitchEquip( i1 , i2 );
	}
	else
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
	}

}


fvoid					GamePlayer::DropEquip( fint32 i1 , fint32 i2 )
{
	if ( i1 < 0 || i1 >= SAET_COUNT || i2 < 0 || i2 >= MAX_ITEM )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return;
	}

	if ( mItemBag.GetItem( i2 ).GetData() )
	{
		AddDanger( GAME_DESTRUCTIVELY_DANGER );
		return;
	}

	mItemBag.DropEquip( i1 , i2 );

	UpdateFightData();
}


fvoid				GamePlayer::AddHp( fint32 hp )
{
	mFightData.Base.HP += hp;

	if ( mFightData.Base.HP > mFightData.Base.MAXHP )
	{
		mFightData.Base.HP = mFightData.Base.MAXHP;
	}
}


fvoid				GamePlayer::AddMp( fint32 mp )
{
	mFightData.Base.MP += mp;

	if ( mFightData.Base.MP > mFightData.Base.MAXMP )
	{
		mFightData.Base.MP = mFightData.Base.MAXMP;
	}
}


fvoid				GamePlayer::Heal( fint32 mode )
{
	switch ( mode )
	{
	case SAHM_ALL:
		{
			mFightData.Base.HP = mFightData.Base.MAXHP;
			
			GamePetMapIter iterEnd = mPet.end();
			for ( GamePetMapIter iter = mPet.begin() ; iter != iterEnd ; ++iter )
			{
				iter->second.GetFightData().Base.HP = iter->second.GetFightData().Base.MAXHP;
			}
		}
		break;
	case SAHM_SELF:
		{
			mFightData.Base.HP = mFightData.Base.MAXHP;
		}
		break;
	case SAHM_PET:
		{
			GamePetMapIter iterEnd = mPet.end();
			for ( GamePetMapIter iter = mPet.begin() ; iter != iterEnd ; ++iter )
			{
				iter->second.GetFightData().Base.HP = iter->second.GetFightData().Base.MAXHP;
			}
		}
		break;
	}

}


//////////////////////////////////////////////////////////////////////////


fbool				GamePlayer::CheckStone( fint32 stone )
{
	return mStone >= stone;
}


fvoid				GamePlayer::IncreaseStone( fint32 stone )
{
	mStone += stone;

	if ( mStone > MAX_STONE )
	{
		mStone = MAX_STONE;
	}
}


fvoid				GamePlayer::DecreaseStone( fint32 stone )
{
	mStone -= stone;

	if ( mStone < 0 )
	{
		mStone = 0;
	}
}


//////////////////////////////////////////////////////////////////////////

fvoid               GamePlayer::UpdateSyncMove()
{
    mMoveData.UpdateSync();
}

fvoid               GamePlayer::SendMsgToAll( netMsgHead* msg , fint32 self )
{
    
    if ( !mMoveData.SyncList.empty() )
    {
        SyncCreatureListIter iterEnd = mMoveData.SyncList.end();
        for ( SyncCreatureListIter iter = mMoveData.SyncList.begin() ; iter != iterEnd ; ++iter )
        {
            if ( *iter == self )
            {
                continue;
            }
            
            GamePlayer* player = gCreatureManager->GetPlayer( *iter );
            
            if ( !player )
            {
                continue;
            }
            
            player->PackMsg( msg );
            player->SendMsg();
        }
    }
    
}

fvoid               GamePlayer::SendMsgToAllEE( netMsgHead* msg , fint32 self )
{
    fbool b = F_FALSE;
    
    if ( !mMoveData.SyncEnter.empty() )
    {
        SEND_RECV_MSG_MOVE_ENTER msg;
        
        SyncCreatureListIter iterEnd = mMoveData.SyncEnter.end();
        for ( SyncCreatureListIter iter = mMoveData.SyncEnter.begin() ; iter != iterEnd ; ++iter )
        {
            if ( *iter == self )
            {
                continue;
            }
            
            GamePlayer* player = gCreatureManager->GetPlayer( *iter );
            
            if ( !player )
            {
                continue;
            }
            
            msg.GUID = *iter;
            msg.X = player->mMoveData.Pos.Grid.x;
            msg.Y = player->mMoveData.Pos.Grid.y;
            
            PackMsg( &msg );
            
            b = F_TRUE;
        }
        
        mMoveData.SyncEnter.clear();
    }
    
    if ( !mMoveData.SyncExit.empty() )
    {
        SEND_RECV_MSG_MOVE_EXIT msg;
        
        SyncCreatureListIter iterEnd = mMoveData.SyncExit.end();
        for ( SyncCreatureListIter iter = mMoveData.SyncExit.begin() ; iter != iterEnd ; ++iter )
        {
            msg.GUID = *iter;
            PackMsg( &msg );
            
            b = F_TRUE;
        }
        
        mMoveData.SyncExit.clear();
    }
    
    if ( b )
    {
        SendMsg();
    }
}